#include "MessagePoster.h"

#include <core/sharedata/login_data.h>
#include <qbkernel/include/qb_base.h>
#include <qbprotocol/include/RequestNetWrapper.h>
#include <qbprotocol/include/SSMsgStruct.h>
#include <qbprotocol/include/rdMessage.h>
#include <qbprotocol/include/rdProto.h>
#include <qbprotocol/include/ssCmnDefine.h>

#ifdef WIN32
#pragma comment(lib, "ws2_32.lib")
#else
#include <arpa/inet.h>
#endif

using namespace qb;

MessagePoster::MessagePoster(int connect_id) : m_connect_id(connect_id) {
  if (connect_id > 0)
    m_connect_id = connect_id;
  else
    m_connect_id = qb::loginData::instance().ConnectID();
}

MessagePoster::MessagePoster(SSRequestMsg* req, const WrapReqFunc& fun,
                             int connect_id)
    : m_req(req), m_reqWrapFunc(fun) {
  if (connect_id > 0)
    m_connect_id = connect_id;
  else
    m_connect_id = qb::loginData::instance().ConnectID();
}

int MessagePoster::send(char* buf, int iLen, int msgType) const {
  xMsgHeadReq_t xhead;
  xhead.msgtype = htonl(msgType);

  int off = 0;
  char sndBuf[Y_RD_SERVICE_MESSAGE_BLOCK_LEN];
  memset(sndBuf, 0x00, Y_RD_SERVICE_MESSAGE_BLOCK_LEN);
  rdMessage::bPack((char*)&xhead, sizeof(xhead), (char*)buf, iLen, sndBuf,
                   &off);

  return qbBase::getMessageKernel()->Send(m_connect_id, sndBuf, off);
}

int MessagePoster::send(MessageReceiver* pr) const {
  char buf[Y_RD_SERVICE_MESSAGE_BLOCK_LEN] = "";
  memset(buf, 0, Y_RD_SERVICE_MESSAGE_BLOCK_LEN);
  if (m_req->m_RequestID == 0) m_req->m_RequestID = GetRequestID();

  qb::proto::Message msg;  // 总的Message
  AddRegMsgHead(*m_req, msg);

  char message_type[128] = "";
  sprintf(message_type, "%d", m_req->m_FuncID);
  msg.SetType(message_type);

  if (m_reqWrapFunc) m_reqWrapFunc(msg, m_req);

  char message_id[128];
  // 新增全局语言字段，Add by LanceZhao 2015.2.26
  msg.SetString("Language", "CHS");  // TODO
  sprintf(message_id, "%ld", m_req->m_RequestID);
  msg.setMessageID(message_id);  ////

  int length = msg.encode(buf, Y_RD_SERVICE_MESSAGE_BLOCK_LEN);

  xMsgHeadReq_t xhead;
  xhead.msgtype = htonl(E_FID_SERVER_QPID);

  int off = 0;
  char sndBuf[Y_RD_SERVICE_MESSAGE_BLOCK_LEN];
  memset(sndBuf, 0, Y_RD_SERVICE_MESSAGE_BLOCK_LEN);
  rdMessage::bPack((char*)&xhead, sizeof(xhead), (char*)buf, length, sndBuf,
                   &off);

  int sendBytes = qbBase::getMessageKernel()->Send(m_connect_id, sndBuf, off);
  log_info("Send message %d, raw size:%d, pack size:%d, sendbytes:%d",
           m_req->m_FuncID, length, off, sendBytes);
  if (sendBytes > 0 && pr) {
    RequestNotifier::instance().registReqReceiver(m_req->m_RequestID, pr);
    pr->addReqs(m_req->m_RequestID);
  }
  return sendBytes > 0 ? m_req->m_RequestID : sendBytes;
}

MessageReceiver::~MessageReceiver() {
  for (auto iter = m_reqs.begin(); iter != m_reqs.end(); ++iter)
    RequestNotifier::instance().unRegistReqReceiver(*iter, this);

  for (const auto& pmi : m_pushes)
    RequestNotifier::instance().unRegistPushReceiver(pmi, this);
}

void MessageReceiver::registPush(const PushMsgInfo& pmi, SSRequestMsg* req,
                                 const WrapReqFunc& fun) {
  auto iter = std::find(m_pushes.begin(), m_pushes.end(), pmi);
  if (iter == m_pushes.end()) {
    m_pushes.insert(pmi);
    RequestNotifier::instance().registPushReceiver(pmi, this);
  }

  if (req != nullptr) {
    req->m_FuncID = pmi.funcId;
    MessagePoster poster(req, fun);
    poster.send(nullptr);
  }
}

void MessageReceiver::unRegistPush(const PushMsgInfo& pmi,
                                   qb::SSRequestMsg* req /*= nullptr*/,
                                   const WrapReqFunc& fun) {
  RequestNotifier::instance().unRegistPushReceiver(pmi, this);
  auto iter = std::find(m_pushes.begin(), m_pushes.end(), pmi);
  if (iter != m_pushes.end()) m_pushes.erase(iter);

  if (req) {
    MessagePoster poster(req, fun);
    poster.send(nullptr);
  }
}
